(ns geometrician.core
  (:require [merpg.2D.core :refer :all]
            [merpg.2D.make-game :refer :all]
            [seesaw.core :refer [alert]]
            [clojure.pprint :refer [pprint]]
            [clojure.java.io :as io]
            [geometrician.State :refer [gen-horizontal-row
                                          cell-at
                                          can-cells-swap?
                                          remove-nice-rows
                                          fill-reduced-colums
                                          contains-horizontal-starys?
                                          swap]])
  (:gen-class))

(alter-var-root #'*out* (constantly *out*))

(defn get-settings []
  (let [conf-file-name (-> (System/getProperty "user.home")
                           (str "/.geometrician"))]
    (when-not (-> conf-file-name
                  io/file
                  .exists)
      (spit conf-file-name ";; This config file is just runnable clojure. You can modify it to do stuff - just make sure to leave this map at the tail position\n {:w 800\n :h 600\n :debug-printing false}"))
    (let [toret (-> conf-file-name
        slurp
        read-string
        eval)]
      (println "Config: " toret)
      toret)))

(defn both-clicked? [cell1 cell2]
  (->> [cell1 cell2]
       (map :clicked?)
       (reduce #(and %1 %2)))) 

(defn -main [& args]
  (let [{*w* :w
       *h* :h
       *debug-printing* :debug-printing} (get-settings)
      clicked-cell (atom {:x 0 :y 0 :clicked? false})
      second-clicked-cell (atom {:x 0 :y 0 :clicked? false})
      handle-clicks (fn [world]   ;;Bloody stateful swing... :P
                      (if-not (both-clicked? @clicked-cell @second-clicked-cell)
                        world
                        (let [{x1 :x y1 :y} @clicked-cell
                              {x2 :x y2 :y} @second-clicked-cell]
                          (reset! clicked-cell {:x 0 :y 0 :clicked? false})
                          (reset! second-clicked-cell {:x 0 :y 0 :clicked? false})

                          (if (can-cells-swap? world [x1 y1] [x2 y2])
                            (swap (vec world) x1 y1 x2 y2)
                            world))))
      handle-nice-rows  (fn [the-world score-out]
                          (loop [the-world the-world
                                 index 0]
                            (let [toret (-> (remove-nice-rows the-world :score-out score-out) 
                                            (fill-reduced-colums (/ *h* 50)))]
                              (when (empty? toret)
                                (pprint the-world)
                                (println "teetti tyhjän tuloksen handle-nice-rows'ssa"))
                              (if (and (contains-horizontal-starys? toret)
                                       (< index 10))
                                (recur toret (inc index))
                                (do
                                  (if (>= index 10)
                                    (println "Rekurroitiin liikaa"))
                                  toret)))))]
  (println "Dimensions: " *w* ", " *h*)
  (merpg.2D.make-game/make-game {:the-world (gen-horizontal-row (/ *w* 50) (/ (- *h* 50) 50))
                                 :score 0}
             :window-width *w*
             :window-height *h*
             :mouse-clicked (fn [[x y]]
                              (when (:clicked? @second-clicked-cell)
                                (reset! clicked-cell {:x 0 :y 0 :clicked? false})
                                (reset! second-clicked-cell {:x 0 :y 0 :clicked? false}))
                              
                              (swap! (if (:clicked? @clicked-cell)
                                       second-clicked-cell
                                       clicked-cell)
                                     assoc :x x
                                     :y  (dec y)
                                     :clicked? true)
                              (println "Clicked at " x ", " (dec y)))
             :update (fn [{world :the-world
                           score :score}]
                       (let [score (atom score)]
                       {:the-world (-> world
                                       handle-clicks
                                       (handle-nice-rows score))
                        :score @score}))
             :title "Geometrikko "
             :pre-drawqueue (fn [{world :the-world
                                  score :score}]
                              (if (:clicked? @clicked-cell)
                                (let [{x :x y :y} @clicked-cell]
                                  (merpg.2D.core/with-color "#555555"
                                    (Rect (* x 50) (* (inc y) 50) 50 50 :fill? true))))
                              (if (:clicked? @second-clicked-cell)
                                (let [{x :x y :y} @second-clicked-cell]
                                  (merpg.2D.core/with-color "#550000"
                                    (Rect (* x 50) (* (inc y) 50) 50 50 :fill? true))))

                              ;; And the HUD!
                              (with-color "#000000"
                                (Draw (str "Score: " score) [0 20])))             
             
             :post-drawqueue (fn [{world :the-world}]
                               (try
                                 (dotimes [x (count world)]
                                   (dotimes [y (count (nth world x))]
                                     (let [cell (cell-at world x y)
                                           x-coord (* 50 x)
                                           y-coord (* 50 (inc (int y)))]
                                       (merpg.2D.core/with-color "#000000"
                                         (Rect x-coord y-coord 50 50))
                                       (cond
                                        (= cell :square)
                                        (merpg.2D.core/with-color "#FF0000"
                                          (Rect x-coord y-coord 25 25 :fill? true))
                                        (= cell :circle)
                                        (merpg.2D.core/with-color "#00FF00"
                                          (Oval x-coord y-coord 25 25 :fill? true))
                                        (= cell :x)
                                        (merpg.2D.core/with-color "#0000FF"
                                          (Line x-coord y-coord (+ x-coord 50) (+ y-coord 50))
                                          (Line x-coord (+ y-coord 50) (+ x-coord 50) y-coord))

                                        (= cell :triangle)
                                        (merpg.2D.core/with-color "#FF00FF"
                                          (Triangle (+ x-coord 25) y-coord
                                                    (+ x-coord (/ 50 4)) (+ y-coord 40)
                                                    (+ x-coord (* (/ 50 4) 3)) (+ y-coord 40)))
                                        (= cell :remove-me!)
                                        (when *debug-printing*
                                          (merpg.2D.core/with-color "#000000"
                                            (Rect x-coord y-coord 50 50 :fill? true)
                                            (merpg.2D.core/with-color "#FFFFFF"
                                              (Draw "RM" [0 0]))))))))

                                 (when *debug-printing*
                                   (merpg.2D.core/with-color "#000000"
                                     (dotimes [x (count world)]
                                       (dotimes [y (count (nth world x))]
                                         (let [coords [(* x 50)
                                                       (* (+ 2 y) 50)]]
                                           (Draw (str x ", " y) coords))))))
                                 (catch Exception ex
                                   (println ex)))))))

